"""
Flask装饰器
"""
import decimal
import json
from datetime import date, datetime
from functools import wraps

import six
from flask import request

from tools import cache, redis_conn


def cached(timeout=5 * 60, key="view/%s"):
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            cache_key = key % request.path
            rv = cache.get(cache_key)
            if rv is not None:
                return rv
            rv = f(*args, **kwargs)
            cache.set(cache_key, rv, timeout=timeout)
            return rv

        return decorated_function

    return decorator


def json_default(obj):
    """将一些无法应映射为 JSON 对象的 Python 对象转换为可映射的对象"""

    if isinstance(obj, datetime):
        obj = obj.strftime("%Y-%m-%d %H:%M:%S")

    elif isinstance(obj, date):
        obj = obj.strftime("%Y-%m-%d")

    elif isinstance(obj, decimal.Decimal):
        obj = str(obj)
    elif six.PY3 and isinstance(obj, bytes):
        return obj.decode("utf8")
    else:
        raise TypeError(obj)

    return obj


def get_and_cache(cache_key="", expire_seconds=60 * 60 * 24):
    """缓存函数运行结果
    :param string cache_key: 缓存key
    :param None|int expire_seconds: 过期时间
    """

    def _cache(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            key = kwargs.pop("cache_key", None)
            if key:
                result = redis_conn.get(key)
                if result:
                    return json.loads(result.decode())
            result = func(*args, **kwargs)
            redis_conn.set(
                cache_key, json.dumps(result, default=json_default), ex=expire_seconds
            )
            return result

        return wrapper

    return _cache
